package com.nulldev.util.web.HttpServer3.pages.brainfuck_backend;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.data.Variables;
import com.nulldev.util.io.file.FileUtil;
import com.nulldev.util.scripting.ScriptAPI.nScripting;
import com.nulldev.util.web.HttpServer3.Response;
import com.nulldev.util.web.HttpServer3.pages.v3.HttpPage3;

public class BrainfuckPage extends HttpPage3 {

	/*
	 * +[--->+<]>++++.-[->++<]>.+++.-[--->++++<]>.--[--->++<]>.++[-->+++<]>.[--->+<]
	 * >----.-[-->+<]>.---[->++++<]>-.+[--->++<]>.--[->++++<]>-.+[->+++<]>.[--->+<]>
	 * +.-[---->+<]>++.+[----->+<]>+.+.+++++.
	 */

	private final ScriptEngine bf;
	private final String payload;

	public BrainfuckPage(final String id, final String payload) {
		this(id, payload, (16 * 1024 * 1024), (1 << 16));
	}

	public BrainfuckPage(final String id, final String payload, final int cycles, final int memory) {
		super(id);
		this.bf = nScripting.cached().getEngineByName("brainfuckse");
		Variables.requireNonNull(this.bf, "bf");
		this.payload = Variables.requireNonNullObject(payload, "payload");
		final Bindings bs = this.bf.createBindings();
		if (cycles > 0)
			bs.put("cycles", cycles);
		if (memory > 0)
			bs.put("memory", memory);
		this.bf.setBindings(bs, ScriptContext.ENGINE_SCOPE);
	}

	@Override
	public Response onRequest(final Request request) {
		try {
			final String out = (String) this.bf.eval(this.payload);
			Variables.requireNonNull(out, "request_object");
			return new Response(200, createStream(out));
		} catch (Throwable t) {
			JVM.errorln(t);
			return new Response(503, FileUtil.getResourceStream(BrainfuckPage.class, "bf_backed_error.html"));
		}
	}
}
